Crate replace_with

Source
Expand description

Temporarily take ownership of a value at a mutable location, and replace it with a new value based on the old one.

šŸ“¦  Crates.io  ā”‚  šŸ“‘  GitHub  ā”‚  šŸ’¬  Chat

This crate provides the function replace_with(), which is like std::mem::replace() except it allows the replacement value to be mapped from the original value.

See RFC 1736 for a lot of discussion as to its merits. It was never merged, and the desired ability to temporarily move out of &mut T doesnā€™t exist yet, so this crate is my interim solution.

Itā€™s very akin to take_mut, though uses Drop instead of std::panic::catch_unwind() to react to unwinding, which avoids the optimisation barrier of calling the extern "C" __rust_maybe_catch_panic(). As such itā€™s up to āˆžx faster. The API also attempts to make slightly more explicit the behavior on panic ā€“ replace_with() accepts two closures such that aborting in the ā€œstandard caseā€ where the mapping closure (FnOnce(T) -> T) panics (as take_mut::take() does) is avoided. If the second closure (FnOnce() -> T) panics, however, then it does indeed abort. The ā€œabort on first panicā€ behaviour is available with replace_with_or_abort().

Ā§Example

Consider this motivating example:

ā“˜
enum States {
    A(String),
    B(String),
}

impl States {
    fn poll(&mut self) {
        // error[E0507]: cannot move out of borrowed content
        *self = match *self {
        //            ^^^^^ cannot move out of borrowed content
            States::A(a) => States::B(a),
            States::B(a) => States::A(a),
        };
    }
}

Depending on context this can be quite tricky to work around. With this crate, however:

enum States {
    A(String),
    B(String),
}

impl States {
    fn poll(&mut self) {
        replace_with_or_abort(self, |self_| match self_ {
            States::A(a) => States::B(a),
            States::B(a) => States::A(a),
        });
    }
}

Huzzah!

FunctionsĀ§

  • Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one.
  • Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one. Lets the closure return a custom value as well.
  • Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one. Aborts on panic.
  • Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one. Aborts on panic. Lets the closure return a custom value as well.
  • Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one. Replaces with Default::default() on panic.
  • Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one. Replaces with Default::default() on panic. Lets the closure return a custom value as well.